package com.foreknow.spring;

import com.foreknow.bean.Admin;
import com.foreknow.service.AdminService;
import org.jdom2.Document;
import org.jdom2.Element;
import org.jdom2.JDOMException;
import org.jdom2.input.SAXBuilder;

import java.io.IOException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * IOC容器
 */
public class ClassPathXmlApplicationContext implements BeanFactory {
    //创建一个容器
    private Map<String,Object> beans = new HashMap<>();
    //解析xml
    public ClassPathXmlApplicationContext() throws Exception {
        //创建一个解析器
        SAXBuilder builder = new SAXBuilder();
        //构造文档
        Document document = builder.build(this.getClass().getClassLoader().getResourceAsStream("beans.xml"));
        //获取到根节点
        Element root = document.getRootElement();
        //获取到子节点  <bean id="u" class="com.foreknow.dao.impl.AdminDaoImpl"></bean>
        List<Element> list = root.getChildren();
        for(int i = 0;i<list.size();i++){
            //获取到集合中某一个子节点(bean)
            Element element = list.get(i);
            //获取到id和class的值
            String id = element.getAttributeValue("id");
            String clazz = element.getAttributeValue("class");  //com.foreknow.dao.impl.AdminDaoImpl
            //需要将clazz转换为对象(反射)
            Object o = Class.forName(clazz).newInstance(); // AdminService对象
            //要将获取到的对象保存到Map容器中
            beans.put(id,o);
            // <property name="adminDao" bean="u"></property>
            for (Element propertyElement :(List<Element>)element.getChildren()){
                String name = propertyElement.getAttributeValue("name"); //adminDao
                String bean = propertyElement.getAttributeValue("bean"); // u
                //从map中获取到u所对应的对象(AdminDaoImpl对象)
                Object beanObject = beans.get(bean);
                //通过反射动态调用set方法  public void setAdminDao(AdminDao adminDao)
                //模拟拼接方法setAdminDao
                String methodName = "set"+name.substring(0,1).toUpperCase()+name.substring(1);//setAdminDao
                Method method = o.getClass().getMethod(methodName,beanObject.getClass().getInterfaces()[0]);
                //调用method中的invoke方法来调用public void setAdminDao(AdminDao adminDao)方法
                method.invoke(o,beanObject);
            }
        }
    }
    @Override
    public Object getBean(String id) {
        return beans.get(id);
    }

    public static void main(String[] args) throws Exception {
        BeanFactory factory = new ClassPathXmlApplicationContext();
        AdminService adminService = (AdminService) factory.getBean("adminService");
        Admin admin = new Admin();
        adminService.save(admin);
    }
}
